package com.suoluo.zenadmin.controllers;

import java.util.Date;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.paoding.rose.web.ControllerInterceptorAdapter;
import net.paoding.rose.web.Invocation;
import net.paoding.rose.web.RequestPath;

import com.suoluo.zenadmin.common.Application;
import com.suoluo.zenadmin.common.StringUtil;
import com.suoluo.zenadmin.controllers.portal.account.LoginManager;
import com.suoluo.zenadmin.service.TaskExecutor;
import com.suoluo.zenadmin.service.account.AccountService;
import com.suoluo.zenadmin.vo.RequestLog;
import com.suoluo.zenadmin.vo.account.AccountVO;

public class PortalInterceptor extends ControllerInterceptorAdapter{
	
	private final ThreadLocal<Long> portalReqContext = new ThreadLocal<Long>();
	
	@Resource(name = "taskExecutor")
	private TaskExecutor taskExecutor;

	@Override
	protected Object before(Invocation inv) throws Exception {
		
		Long reqMillis = portalReqContext.get();
		//如果内部进行了转发，则不进行重新设置当前时间了，否则会重复设置
		if (reqMillis == null){
			portalReqContext.set(System.currentTimeMillis());
		}
		HttpServletRequest request = inv.getRequest();
		String host = request.getHeader("Host");
		if (host == null){
			host = request.getHeader("host");
			logger.error("host is null,host="+host);
		}
//		System.out.println("rosePath:" + inv.getRequestPath().getRosePath()+",queryString:"+request.getQueryString());
		//如果主机名是以zentravel.cn开头，则需要重定向到www.zentravel.cn
		if (host != null && host.startsWith("zentravel.cn")){
			HttpServletResponse response = inv.getResponse();
			response.setStatus(301);   
			RequestPath path = inv.getRequestPath();
			StringBuilder url = new StringBuilder("http://www.zentravel.cn");
			url.append(path.getCtxpath()).append(path.getRosePath());
			if (!StringUtil.isEmpty(request.getQueryString())){
				url.append("?").append(request.getQueryString());
			}
	        response.setHeader( "Location",url.toString());   
	        response.setHeader( "Connection", "close" );   
			return null;
		}
		LoginManager loginMgr = LoginManager.getInstance();
		if (!loginMgr.isLogined(inv) && loginMgr.isRemembered(inv)){
			AccountService service = Application.getInstance().getBean("accountService", AccountService.class);
			Object obj = loginMgr.getRememberInfo(inv);
			AccountVO loginInfo = service.findAccount((Integer) obj);
			if (loginInfo == null){
				loginMgr.logout(inv);
			}else{
				loginMgr.login(inv, loginInfo);
			}
		}
		return super.before(inv);
	}
	
	
	/**
	 * date：发出请求时候的日期。
　　time：发出请求时候的时间。注意：默认情况下这个时间是格林威治时间，比我们的北京时间晚8个小时，下面有说明。
　　c-ip：客户端IP地址。
　　cs-method：请求中使用的HTTP方法，GET/POST。
　　cs-uri-stem：URI资源，记录做为操作目标的统一资源标识符（URI），即访问的页面文件。
　　cs-uri-query：URI查询，记录客户尝试执行的查询，只有动态页面需要URI查询，如果有则记录，没有则以连接符-表示。即访问网址的附带参数。
　　sc-status：协议状态，记录HTTP状态代码，200表示成功，403表示没有权限，404表示找不到该页面，具体说明在下面。
　　sc-substatus：协议子状态，记录HTTP子状态代码。
　　sc-win32-status：Win32状态，记录Windows状态代码，参照chxwei博客上前几天发的日志“IIS中的sc-win32-status——Win32状态详细说明”的说明。
　　sc-bytes：服务器发送的字节数。
　　cs-bytes：服务器接受的字节数。
　　time-taken：记录操作所花费的时间，单位是毫秒。
　　cs-version：记录客户端使用的协议版本，HTTP或者FTP。
　　cs-host:记录主机头名称，没有的话以连接符-表示。注意：为网站配置的主机名可能会以不同的方式出现在日志文件中，原因是HTTP.sys使用Punycode编码格式来记录主机名。 特别注意：本站所有转载文章言论不代表本站观点，本站所提供的摄影照片，插画，设计作品，如需使用，请与原作者联系
　　cs(User-Agent)：用户代理，客户端浏览器、操作系统等情况。
　　cs(Cookie)：记录发送或者接受的Cookies内容，没有的话则以连接符-表示。
　　cs(Referer)：引用站点，即访问来源。 
	 */
	@Override
	public void afterCompletion(Invocation inv, Throwable ex) throws Exception {
		HttpServletResponse resp = inv.getResponse();
		HttpServletRequest req = inv.getRequest();
		
//		Enumeration<String> headers =  req.getHeaderNames();
		
		Long reqMillis = portalReqContext.get();
		//内部转发后，在执行afterCompletion，会清除这个值
		if (reqMillis == null){
			return;
		}
		portalReqContext.set(null);
		RequestLog log = new RequestLog();
		String userAgent = req.getHeader("user-agent");
		log.setAgent(StringUtil.substring(userAgent, 128,"-"));
		log.setCost(System.currentTimeMillis() - reqMillis.longValue());
		String host = req.getRemoteHost();
		log.setHost(StringUtil.substring(host, 32,"-"));
		
		log.setIp(req.getRemoteAddr());
		log.setLength(req.getContentLength());
		log.setMethod(req.getMethod());
		String referer = req.getHeader("referer");
		log.setReferer(StringUtil.substring(referer, 128, "-"));
		log.setTime(new Date(reqMillis.longValue()));
		String url = req.getRequestURI();
		log.setUrl(StringUtil.substring(url, 64, "/"));
		
		//记录日志
//		TaskExecutor executor = Application.getInstance().getBean("executor", TaskExecutor.class);
		taskExecutor.addRequestLog(log);
//		log.setAgent(agent)
//		StringBuilder reqParam = new StringBuilder();
//		reqParam.append("date-time=").append(new Date())
//				.append(",ip=").append(req.getRemoteAddr())
//				.append(",rhost=").append(req.getRemoteHost())
//				.append(",rport=").append(req.getRemotePort())
//				.append("ruser=").append(req.getRemoteUser())
//				.append(",contentLength=").append(req.getContentLength())
//				.append(",method=").append(req.getMethod())
//				.append(",ruri=").append(req.getRequestURI())
//				.append(",url=").append(req.getRequestURL());
//		while (headers.hasMoreElements()){
//			String headerName = headers.nextElement();
//			reqParam.append(",").append(headerName+"=").append(req.getHeader(headerName));
//		}
//		super.afterCompletion(inv, ex);
//		System.out.println(reqParam);
		
	}
}
